package ch01

import (
	"context"
	"fmt"
	"sync"
	"time"
)

func ContextDemo1() {
	// 创建一个带有截止日期的context.Context
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) //context.WithDeadline(context.Background(), time.Now().Add(1*time.Second))
	defer cancel()

	// 启动一个goroutine执行任务
	go func() {
		for {
			select {
			case <-ctx.Done():
				// 如果接收到取消信号，立即退出goroutine
				fmt.Println("Task canceled")
				return
			default:
				// 模拟耗时的任务
				fmt.Println("Task running")
				time.Sleep(500 * time.Millisecond)
			}
		}
	}()

	// 等待一段时间后取消任务
	time.Sleep(2 * time.Second)
	cancel()
	fmt.Println("Task canceled by main goroutine")
}

func ContextDemo2() {
	// 创建根context.Context
	ctx := context.Background()

	// 使用context.WithValue创建带有请求范围的数据的context.Context
	ctxWithValue := context.WithValue(ctx, "requestID", "123456")

	// 在其他函数或goroutine中使用context.Context
	for i := 0; i < 10; i++ {
		go func(x int, ctx context.Context) {
			requestID, ok := ctx.Value("requestID").(string)
			if !ok {
				fmt.Println("Invalid requestID")
				return
			}
			fmt.Println("routine: ", x, ", RequestID: ", requestID)
		}(i, ctxWithValue)
	}

	time.Sleep(2 * time.Second)
}

func ContextDemo3() {
	// 创建一个空的、无值的context.Context
	ctx := context.Background()

	// 创建一个带有请求范围的数据的context.Context，并将其传递给goroutine1
	ctxWithValue := context.WithValue(ctx, "data", "Hello, World!")
	var wg sync.WaitGroup
	wg.Add(2)

	// 启动goroutine1，在其中将数据写入context.Context
	go func(ctx context.Context) {
		defer wg.Done()
		// 将数据写入context.Context
		ctx = context.WithValue(ctx, "data", "Hello, Golang!")
		fmt.Println("goroutine1: data has been written to context.Context")
	}(ctxWithValue)
	time.Sleep(1 * time.Second)
	// 启动goroutine2，在其中读取context.Context中的数据
	go func(ctx context.Context) {
		defer wg.Done()
		// 从context.Context中读取数据
		data := ctx.Value("data")
		fmt.Println("goroutine2: data from context.Context:", data)
	}(ctxWithValue)

	wg.Wait()
}
